
import { ENUM_AUDIO_CLIP, ENUM_GAME_STATUS, ENUM_WATER_TYPE } from "../Enum";
import { privacyChannel } from "../Script/privacyChannel";
import { StaticInstance } from "../StaticInstance";
import { toXY } from "../Utils";
import AudioManager from "../manager/AudioManager";
import DataManager, { DATA_GAME } from "../manager/DataManager";
import PoolManager from "../manager/PoolManager";
import SdkManager from "../manager/SdkManager";
import ToastManager from "../manager/ToastManager";
import Water, { WaterInfo } from "./Water";

const { ccclass, property } = cc._decorator;

export class TopWater {
    public color: number
    public nums: number
}

@ccclass
export default class Bottle extends cc.Component {

    @property([cc.Integer])
    colors: number[] = []
    // 索引
    bottleIndex: number = -1
    // 绘画水块父节点
    waterRoot: cc.Node = null
    // 水柱节点
    waterColumn: cc.Node = null
    // 瓶子所有水信息
    waters: Water[] = []
    // 左右瓶口临界点
    markLeft: cc.Node = null
    markRight: cc.Node = null
    // 绘画尺寸
    disLeft: number = 0
    disRight: number = 0
    disHeight: number = 0
    // 初始位置
    startPos: cc.Vec2 = null
    offsetHeight: number = 30
    offsetHeight2: number = 100
    // 目标bottle
    bottleTarget: Bottle = null
    // 水位信息
    topWater: TopWater = null
    // 倒水方向
    isPourLeft: boolean = false
    // 旋转
    angleSpeed: number = 100
    // 状态执行转角度
    isStateAngle: boolean = false
    isStateAngleBack: boolean = false
    // 状态瓶子相互倒水
    isStatePour: boolean = false
    // 水柱显示
    isStateWaterColumn: boolean = false
    // 倒水音效
    waterSoundIndex: number = -1

    init(index: number, colors?: number[]) {
        this.bottleIndex = index
        if (!colors) {
            colors = this.colors
        } else {
            this.colors = colors
        }
        // 节点
        this.waterRoot = cc.find('mask/water_root', this.node)
        this.waterColumn = this.node.getChildByName('water_column')
        this.markLeft = this.node.getChildByName('mark_left')
        this.markRight = this.node.getChildByName('mark_right')
        // 初始化数据
        const { width, height } = this.waterRoot
        this.disRight = width / 2
        this.disLeft = -this.disRight
        this.disHeight = height / DATA_GAME.nums
        this.startPos = this.node.getPosition()
        this.waterRoot.destroyAllChildren()
        // 渲染颜色水块
        for (let i = 0; i < colors.length; i++) {
            let water = PoolManager.instance.getNode('Water', this.waterRoot)
            let waterComp = water.getComponent(Water);
            let info = new WaterInfo()
            info.color = colors[i]
            info.left_down = cc.v2(this.disLeft, i * this.disHeight)
            info.left_up = cc.v2(this.disLeft, (i + 1) * this.disHeight)
            info.right_down = cc.v2(this.disRight, i * this.disHeight)
            info.right_up = cc.v2(this.disRight, (i + 1) * this.disHeight)
            waterComp.init(info)
            waterComp.setPos(cc.v2(0, (i + 1) * this.disHeight), cc.v2(0, i * this.disHeight))
            this.waters.push(waterComp)
        }
        // 水满检测
        this.checkWaterFill(true)
        // 注册点击事件
        this.node.on('touchstart', this.onTouchStart, this)
    }

    reset() {
        this.node.setSiblingIndex(0)
        for (let i = 0; i < this.waters.length; i++) {
            let waterComp = this.waters[i]
            let info = waterComp.info
            info.left_down = cc.v2(this.disLeft, i * this.disHeight)
            info.left_up = cc.v2(this.disLeft, (i + 1) * this.disHeight)
            info.right_down = cc.v2(this.disRight, i * this.disHeight)
            info.right_up = cc.v2(this.disRight, (i + 1) * this.disHeight)
            waterComp.reset(info)
        }
    }

    onTouchStart() {
        if (DataManager.instance.status == ENUM_GAME_STATUS.UNRUNING) return
        if (this.checkState()) {
            // 加锁
            if (this.node.getChildByName('locked').active) {
                privacyChannel.getChannel().showVideo(() => {

                    AudioManager.instance.playSound(ENUM_AUDIO_CLIP.UNLOCK)
                    this.node.getChildByName('locked').active = false
                })
                return
            }
            AudioManager.instance.playSound(ENUM_AUDIO_CLIP.CLICK_ITEM)
            if (StaticInstance.gameManager.bottles.length) {
                if (StaticInstance.gameManager.bottles[0] == this) {
                    StaticInstance.gameManager.bottles[0].setActive(false)
                } else {
                    // 判定执行倒水
                    // console.log(StaticInstance.gameManager.bottles[0].canPourWater(this))
                    if (StaticInstance.gameManager.bottles[0].canPourWater(this)) {
                        StaticInstance.gameManager.bottles[0].pourWater(this)
                    } else {
                        StaticInstance.gameManager.bottles[0].setActive(false)
                    }
                }
                StaticInstance.gameManager.bottles = []
            } else {
                if (this.isEmptyBottle()) {
                    ToastManager.instance.show('空瓶子~', { gravity: 'TOP', bg_color: cc.color(226, 69, 109, 255) })
                } else {
                    StaticInstance.gameManager.bottles.push(this)
                    this.setActive()
                }
            }
        }
    }


    // 判定是否为空瓶子
    isEmptyBottle() {
        return this.waters.length <= 0
    }

    // 标记选中瓶子
    setActive(bool: boolean = true) {
        if (bool) {
            this.node.setSiblingIndex(100)
            cc.Tween.stopAllByTarget(this.node)
            cc.tween(this.node).to(0.2, { y: this.startPos.y + this.offsetHeight }).start()
        } else {
            this.node.setSiblingIndex(0)
            cc.Tween.stopAllByTarget(this.node)
            cc.tween(this.node).to(0.2, { y: this.startPos.y }).start()
        }
    }
    // 容纳数
    getLimitWaterNum() {
        return DATA_GAME.nums - this.waters.length
    }

    // 获取瓶子顶部水信息
    getWaterTop() {
        const info: TopWater = { color: -1, nums: 0 }
        for (let i = this.waters.length - 1; i >= 0; i--) {
            const waterComp = this.waters[i]
            const color = waterComp.info.color
            if (info.color == -1) {
                info.color = color
            }
            if (info.color == color) {
                info.nums += 1
            } else {
                break
            }
        }
        return info
    }

    // 判定是否可以倒水
    canPourWater(target: Bottle) {
        const currentInfo = this.getWaterTop()
        const targetInfo = target.getWaterTop()
        // console.log(currentInfo, targetInfo, target.getLimitWaterNum())
        // && (targetInfo.nums + currentInfo.nums) <= DATA_GAME.nums
        if (targetInfo.nums == 0 || (targetInfo.color == currentInfo.color && target.getLimitWaterNum() > 0)) return true
        return false
    }


    // 倒水
    pourWater(target: Bottle, topWater: TopWater = null) {
        this.bottleTarget = target
        this.topWater = topWater
        if (!this.topWater) {
            this.topWater = this.getWaterTop()
            const limit = target.getLimitWaterNum()
            if (limit < this.topWater.nums) this.topWater.nums = limit
            //倒水步骤记录
            StaticInstance.gameManager.steps.push({ bottleFrom: this.bottleIndex, bottleTo: target.bottleIndex, topWater: this.topWater })

        }
        this.isPourLeft = target.node.x < this.node.x
        // 初始化target水位信息
        target.initTargetWater(this.topWater)
        cc.Tween.stopAllByTarget(this.node)
        let x = target.node.x, y = target.node.y + this.offsetHeight2
        // 状态更新
        this.isStatePour = true
        target.isStatePour = true
        this.isStateAngle = true
        cc.tween(this.node).to(0.5, { x, y }).call(() => this.isStateWaterColumn = true).start()
    }

    // 倒水绘制
    onPourWater() {
        let count = 0
        let ratios: number[] = []
        for (let i = this.waters.length - 1; i >= 0; i--) {
            const waterComp = this.waters[i]
            let info = waterComp.info
            let up = waterComp.getPos(ENUM_WATER_TYPE.UP, true)
            let down = waterComp.getPos(ENUM_WATER_TYPE.DOWN, true)
            let leftDown = waterComp.getPos(ENUM_WATER_TYPE.LEFT_DOWN, true)
            let leftUp = waterComp.getPos(ENUM_WATER_TYPE.LEFT_UP, true)
            let rightDown = waterComp.getPos(ENUM_WATER_TYPE.RIGHT_DOWN, true)
            let rate = (leftDown.y - leftUp.y) / (leftDown.x - leftUp.x)
            let ld = leftDown.y - (leftDown.x * rate)
            let rd = rightDown.y - (rightDown.x * rate)
            let mark = this.isPourLeft ? this.markLeft : this.markRight
            let markPos = mark.convertToWorldSpaceAR(cc.Vec2.ZERO)
            let lrdPos = this.isPourLeft ? waterComp.node.convertToWorldSpaceAR(waterComp.getPos(ENUM_WATER_TYPE.LEFT_DOWN)) : waterComp.node.convertToWorldSpaceAR(waterComp.getPos(ENUM_WATER_TYPE.RIGHT_DOWN))
            let downY = i == 0 ? lrdPos.y : down.y
            if (markPos.y > downY) {
                let ratio = 0
                if (markPos.y <= up.y) {
                    up = markPos
                    if (this.isStateAngle) {
                        // 显示水柱
                        this.isStateWaterColumn && this.bottleTarget.setWaterColumn(true, this.topWater.color, mark)
                    }
                }
                if (i == 0) {
                    if (this.isPourLeft) {
                        info.left_down = waterComp.getPos(ENUM_WATER_TYPE.LEFT_DOWN)
                        if (markPos.y < waterComp.node.convertToWorldSpaceAR(waterComp.getPos(ENUM_WATER_TYPE.RIGHT_DOWN)).y) {
                            info.right_down = waterComp.node.convertToNodeSpaceAR(cc.v2((markPos.y - rd) / rate, markPos.y));
                        } else {
                            info.right_down = waterComp.node.convertToNodeSpaceAR(cc.v2((down.y - rd) / rate, down.y));
                        }
                        ratio = (markPos.y - waterComp.node.convertToWorldSpaceAR(waterComp.getPos(ENUM_WATER_TYPE.LEFT_DOWN)).y) / (waterComp.getPos(ENUM_WATER_TYPE.UP, true).y - waterComp.node.convertToWorldSpaceAR(waterComp.getPos(ENUM_WATER_TYPE.LEFT_DOWN)).y)
                    } else {
                        info.right_down = waterComp.getPos(ENUM_WATER_TYPE.RIGHT_DOWN)
                        if (markPos.y < waterComp.node.convertToWorldSpaceAR(waterComp.getPos(ENUM_WATER_TYPE.LEFT_DOWN)).y) {
                            info.left_down = waterComp.node.convertToNodeSpaceAR(cc.v2((markPos.y - ld) / rate, markPos.y));
                        } else {
                            info.left_down = waterComp.node.convertToNodeSpaceAR(cc.v2((down.y - ld) / rate, down.y));
                        }
                        ratio = (markPos.y - waterComp.node.convertToWorldSpaceAR(waterComp.getPos(ENUM_WATER_TYPE.RIGHT_DOWN)).y) / (waterComp.getPos(ENUM_WATER_TYPE.UP, true).y - waterComp.node.convertToWorldSpaceAR(waterComp.getPos(ENUM_WATER_TYPE.RIGHT_DOWN)).y)
                    }
                } else {
                    info.left_down = waterComp.node.convertToNodeSpaceAR(cc.v2((down.y - ld) / rate, down.y));
                    info.right_down = waterComp.node.convertToNodeSpaceAR(cc.v2((down.y - rd) / rate, down.y));
                    ratio = (markPos.y - waterComp.getPos(ENUM_WATER_TYPE.DOWN, true).y) / (waterComp.getPos(ENUM_WATER_TYPE.UP, true).y - waterComp.getPos(ENUM_WATER_TYPE.DOWN, true).y)
                }
                info.right_up = waterComp.node.convertToNodeSpaceAR(cc.v2((up.y - rd) / rate, up.y));
                info.left_up = waterComp.node.convertToNodeSpaceAR(cc.v2((up.y - ld) / rate, up.y));
                if (count < this.topWater.nums) {
                    ratio = ratio >= 1 ? 0 : 1 - ratio
                    ratios.push(ratio)
                }
            } else {
                if (this.isStateAngle) {
                    if (count < this.topWater.nums) {
                        ratios.push(1)
                        waterComp.node.active = false
                        if (count == this.topWater.nums - 1) {
                            this.isStateAngle = false
                            this.isStateWaterColumn = false
                            // 涨水
                            this.bottleTarget.updateTargetWater(ratios);
                            // 隐藏水柱
                            this.bottleTarget.setWaterColumn(false)
                            // 瓶子回程
                            this.bottleBack()
                        }
                    }
                }
            }
            waterComp.reset(info)
            count++
        }
        if (this.isStateAngle) {
            ratios = ratios.reverse()
            // 涨水
            this.isStateWaterColumn && this.bottleTarget.updateTargetWater(ratios);
        }
    }

    // 点击前置状态判定
    checkState() {
        return !this.isStateAngle && !this.isStateAngleBack && !this.isStatePour
    }

    // 初始化水位起始信息
    initTargetWater(topWater: TopWater) {
        const len = this.waters.length
        for (let i = 0; i < topWater.nums; i++) {
            const ii = i + len
            const color = topWater.color
            let water = PoolManager.instance.getNode('Water', this.waterRoot)
            let waterComp = water.getComponent(Water);
            let waterInfo = new WaterInfo()
            waterInfo.color = color
            waterInfo.left_down = cc.v2(this.disLeft, ii * this.disHeight)
            waterInfo.left_up = cc.v2(this.disLeft, ii * this.disHeight)
            waterInfo.right_down = cc.v2(this.disRight, ii * this.disHeight)
            waterInfo.right_up = cc.v2(this.disRight, ii * this.disHeight)
            waterComp.init(waterInfo)
            waterComp.setPos(cc.v2(0, (ii + 1) * this.disHeight), cc.v2(0, ii * this.disHeight))
            this.waters.push(waterComp)
        }
    }

    // 执行修改瓶子水位
    updateTargetWater(ratios: number[]) {
        let count = 0
        for (let i = this.waters.length - 1; i >= 0; i--) {
            let waterComp = this.waters[i]
            if (count >= ratios.length) return
            let ratio = ratios[count]
            let info = waterComp.info
            let y = this.disHeight * (ratio + i)
            info.right_up = cc.v2(info.right_up.x, y)
            info.left_up = cc.v2(info.left_up.x, y)
            waterComp.reset(info)
            count++
        }
    }

    // 水柱效果
    async setWaterColumn(bool: boolean, color?: number, markNode?: cc.Node) {
        if (bool) {
            if (this.waterSoundIndex == -1) {
                this.waterSoundIndex = await AudioManager.instance.playSound(ENUM_AUDIO_CLIP.WATER)
            }
            cc.Tween.stopAllByTarget(this.waterColumn)
            this.waterColumn.active = true
            this.waterColumn.color = new cc.Color().fromHEX(DATA_GAME.colors[color])
            const pos1 = toXY(markNode, this.node.parent)
            const pos2 = toXY(this.waterColumn, this.node.parent)
            const dis = Math.abs(pos1.y - pos2.y)
            this.waterColumn.height = dis / this.node.scale
        } else {
            cc.Tween.stopAllByTarget(this.waterColumn)
            // 水柱缓动下落消失效果
            cc.tween(this.waterColumn).to(0.2, { height: 0 }).call(() => {
                this.waterColumn.active = false
            }).start()
            // 延迟音效
            this.scheduleOnce(() => {
                AudioManager.instance.stopSound(this.waterSoundIndex)
                this.waterSoundIndex = -1
            }, 0.5)
        }
    }

    // 回程
    bottleBack() {
        for (let i = 0; i < this.waters.length; i++) {
            const waterComp = this.waters[i]
            let info = waterComp.info
            let y = this.disHeight + waterComp.getPos(ENUM_WATER_TYPE.RIGHT_DOWN).y
            info.left_down = waterComp.getPos(ENUM_WATER_TYPE.LEFT_DOWN)
            info.left_up = cc.v2(info.left_up.x, y)
            info.right_down = waterComp.getPos(ENUM_WATER_TYPE.RIGHT_DOWN)
            info.right_up = cc.v2(info.right_up.x, y)
        }
        let count = 0
        for (let i = this.waters.length - 1; i >= 0; i--) {
            if (count < this.topWater.nums) {
                const waterComp = this.waters[i]
                waterComp.node.destroy()
                this.waters.splice(i, 1)
            }
            count++
        }
        this.isStatePour = false
        this.bottleTarget.isStatePour = false
        this.isStateAngleBack = true
        cc.Tween.stopAllByTarget(this.node)
        cc.tween(this.node).to(0.5, { x: this.startPos.x, y: this.startPos.y, angle: 0 }).start()
        this.checkWaterFill()
        this.checkOver()
    }

    // 判断是否水满
    checkWaterFill(isInit: boolean = false) {
        const currentTop = this.getWaterTop()
        const currentTick = this.node.getChildByName('tick')
        const currentEff = this.node.getChildByName('eff_full').getComponent(cc.Animation)
        if (currentTop.nums >= DATA_GAME.nums) {
            currentTick.active = true
            currentEff.play()
        } else {
            currentTick.active = false
        }
        let targetTick = null
        if (this.bottleTarget) {
            const taregetTop = this.bottleTarget.getWaterTop()
            targetTick = this.bottleTarget.node.getChildByName('tick')
            const targetEff = this.bottleTarget.node.getChildByName('eff_full').getComponent(cc.Animation)
            if (taregetTop.nums >= DATA_GAME.nums) {
                switch (privacyChannel.channel) {
                    case "vivo1":
                        if (privacyChannel.getChannel().getCtrl("p15")) {
                            privacyChannel.getChannel().showVideo(() => {

                            })
                        }
                        break
                    case "oppo1":
                        if (privacyChannel.getChannel().getCtrl("p13")) {
                            privacyChannel.getChannel().showVideo(() => { })
                        }
                        break
                }
                targetTick.active = true
                targetEff.play()
            } else {
                targetTick.active = false
            }
        }
        if ((currentTick.active || (targetTick && targetTick.active)) && !isInit) AudioManager.instance.playSound(ENUM_AUDIO_CLIP.FULL)
    }

    // 判定胜利与否
    checkOver() {
        StaticInstance.gameManager.onGameCheck()
    }

    // 同色
    checkSomeWater() {
        const color = this.waters[0].info.color
        for (let i = 0; i < this.waters.length; i++) {
            const waterComp = this.waters[i]
            if (waterComp.info.color != color) return false
        }
        return true
    }

    update(dt: number): void {
        // if (Math.abs(this.node.angle) >= 90) return
        if (this.isStateAngle) {
            // if (this.isStateWaterColumn) this.angleSpeed = 80 
            this.node.angle += dt * this.angleSpeed * (this.isPourLeft ? 1 : -1)
            this.onPourWater()
        }
        if (this.isStateAngleBack) {
            if (this.node.angle == 0) {
                this.isStateAngleBack = false
                this.reset()
            } else {
                this.onPourWater()
            }
        }
    }
}
